library msnetservice;

export 'result_data.dart';
import 'dart:convert';
import 'dart:developer';
import 'dart:io';
import 'dart:typed_data';

import 'package:dio/dio.dart';
import 'result_data.dart';
import 'dio_instance.dart';
import 'package:flutter/material.dart';

enum Method {
  GET,
  POST,
  UPLOAD,
  DOWNLOAD,
  DELETE,
}

class NetService {
  static const String _TAG = "NetService";

  /// get请求
    get(String url,
      {Map<String, dynamic>? params,
      BuildContext? context,
      bool? showLoad, bool showLog = true}) async {
    return await request(url,
        method: Method.GET,
        params: params,
        context: context,
        showLoad: showLoad ?? false, showLog: showLog);
  }

  /// post请求
  post(String url,
      {Map<String, dynamic>? params,
      BuildContext? context,
      bool? showLoad, bool showLog = true}) async {
    return await request(url,
        method: Method.POST,
        params: params,
        context: context,
        showLoad: showLoad ?? false,
        showLog: showLog);
  }

  /// delete请求
  delete(String url,
      {Map<String, dynamic>? params,
        BuildContext? context,
        bool showLoad = false, bool showLog = true}) async {
    return await request(url,
        method: Method.DELETE,
        params: params,
        context: context,
        showLoad: showLoad, showLog: showLog);
  }

  /// 附件上传
  upLoad(
    File file,
    String fileName,
    String url, {
    Map<String, dynamic>? params,
  }) async {
    return await request(url,
        method: Method.UPLOAD, params: params, file: file, fileName: fileName);
  }

  /// 附件下载
  download(String url, String savePath) async {
    return await request(url, method: Method.DOWNLOAD, fileSavePath: savePath);
  }

  ///  请求部分
  request(String url,
      {Method? method,
      Map<String, dynamic>? params,
      File? file,
      String? fileName,
      String? fileSavePath,
      BuildContext? context,
      bool showLoad = false,
      bool showLog = true,}) async {
    try {
      Response? response;

      Dio dioInstance = DioInstance.createInstance();
      var headers = await getHeaders();
      if (headers != null) {
        dioInstance.options.headers = headers;
      }
      var baseUrl = await getBasicUrl();
      dioInstance.options.baseUrl = baseUrl;

      // 打印网络日志
      StringBuffer requestParamLog = new StringBuffer();
      requestParamLog.write("$_TAG ");
      requestParamLog.write("Url:");
      requestParamLog.write(baseUrl);
      requestParamLog.write(url);
      requestParamLog.write("\n");
      requestParamLog.write("$_TAG ");
      requestParamLog.write("params:");
      requestParamLog.write(json.encode(params));
      requestParamLog.write("\n");
      requestParamLog.write("$_TAG ");
      requestParamLog.write("headers: " + headers.toString());

      if(showLog != false) {
        printLog(requestParamLog.toString());
      }

      switch (method) {
        case Method.GET:
          response = await dioInstance.get(url, queryParameters: params,
              options: Options(
                  validateStatus: (status) {   // 避免出现428直接报错
                    return status! <= 500;
                  }
              )
          );
          break;
        case Method.POST:
          // body 类型分为
          // multipart/form-data,
          // application/x-www-form-urlencoded,
          // raw, 也就是 application/json
          // (binary, GraphQL暂不考虑)

          response = await dioInstance.post(url, data: params,
              options: Options(
                  contentType: "application/json",
                  validateStatus: (status) {   // 避免出现428直接报错
                    return status! <= 500;
                  }
              )
          );
          break;
        case Method.DELETE:
          response = await dioInstance.delete(url, data: params,
              options: Options(
                  validateStatus: (status) {   // 避免出现428直接报错
                    return status! <= 500;
                  }
              )
          );

          break;
        case Method.UPLOAD:
          {
            dioInstance.options.contentType = "form-data";

            FormData formData;
            /// files是参数名, 必须和接口一致, fileName是文件的文件名
            params!["uploadImg"] = await MultipartFile.fromFile(file!.path, filename: fileName);
            formData = FormData.fromMap(params);

            response = await dioInstance.post(url, data: formData, queryParameters: params);
            break;
          }
        case Method.DOWNLOAD:
          response = await dioInstance.download(url, fileSavePath);
          break;
      }

      if(response?.data is Uint8List) {
        // logs("返回结果Uint8List: ${String.fromCharCodes(response.data)}");  // 中文会乱码
        // logs("返回结果Uint8List: ${utf8.decode(response.data)}");
        response?.data = utf8.decode(response.data);
      }else{
        // logs("返回结果: ${response.data}");
      }
      // logs("返回结果: ${response}");
      return await handleDataSource(response!, method!, url: url);
    } catch (exception) {
      printLog("$_TAG net exception= " + exception.toString());
      return ResultData(msg: "网络连接异常", result: false, url: url);
    }
  }

  /// 数据处理
  static handleDataSource(Response response, Method method, {String url = ""}) {
    ResultData resultData;
    String errorMsg = "";
    int? statusCode;
    const HTTP_OK = 200;
    statusCode = response.statusCode;
    printLog("$_TAG statusCode:" + statusCode.toString() + " url: ${url}");
    if (method == Method.DOWNLOAD) {
      if (statusCode == HTTP_OK) {
        /// 下载成功
        resultData = ResultData(msg: '下载成功', result: true);
      } else {
        /// 下载失败
        resultData = ResultData(msg: '下载失败', result: false);
      }
    } else {
      Map<String, dynamic> data;

      if (response.data is Map) {
        data = response.data;
      } else {
        data = json.decode(response.data);
      }

      //处理错误部分
      try {
        resultData = ResultData.response(data);
      } catch (exception) {
        resultData = ResultData(msg: exception.toString(), result: true, url: url);
      }
      // if (statusCode != HTTP_OK) {
      //   errorMsg = "网络请求错误,状态码:" + statusCode.toString();
      //   resultData = ResultData(errorMsg, false, url: url);
      // } else {
      //
      // }
    }
    return resultData;
  }

  getHeaders() {
    return null;
  }

  getBasicUrl() {
    return null;
  }

  static void printLog(String logStr, {tag}) {
    bool print = true;
    if (print) {
      String tagLog;
      if (tag != null) {
        tagLog = tag + logStr;
      } else {
        tagLog = logStr;
      }
      // debugPrint(tagLog);
      log(tagLog);
    }
  }

}
